<?php
/**
* 公共入口:设置系统常量，配置数据库，配置错误、异常处理方式，
* 配置LIB类自动加载，表单Token自动验证。
*/


// 屏蔽废弃或提醒类错误消息
error_reporting(0);

// 拒绝非法文件引用
define('IN_MY_PHP', true);

// 设置Session前缀来区别不同的应用
defined('APPID') || define('APPID', 'sw');

// 一些用到的常量
defined('CRLF') || define('CRLF', "\r\n");
defined('DS') || define('DS', DIRECTORY_SEPARATOR);

// ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
// -- 根据文件的相对位置计算出来项目根目录
define('PROJECT_PATH', rtrim(dirname(dirname(__FILE__)), DS) . DS);
define('LIB_PATH', rtrim(dirname(__FILE__), DS) . DS);
// -- 也可以写死成下面的固定形式
// define('PROJECT_PATH', 'path-to-project' . DS);
// define('LIB_PATH', PROJECT_PATH . 'path-to-lib' . DS);
// ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

if (PHP_SAPI != 'cli') {
  // 脚本的相对路径和根路径的差值
  define('_CRPATH', str_ireplace(DS, '/', str_ireplace(PROJECT_PATH, DS, rtrim(getcwd(), DS).DS)));
  // URL的根路径 eg:/xx/... 和服务器根目录相对应
  define('_WEBPATH', str_ireplace(_CRPATH, '/', str_ireplace(DS, '/', rtrim(dirname($_SERVER['SCRIPT_NAME']), DS).DS)));
  // 带协议和域名及端口的项目url前缀，用于兼容linux的路径
  // Web-protocol :// hostname[:port] / path / [;parameters][?query]#fragment
  define('PROJECT_URL', 'http://' . $_SERVER['HTTP_HOST'] . _WEBPATH);
  define('UPLOAD_URL', PROJECT_URL.'uploads/'); //UPLOAD URL路径
  define('PLUGIN_URL', PROJECT_URL.'plugins/'); //plugins URL路径
	define('IS_LOCAL_REQUEST', preg_match('/^(127(\\.\\d+){3}|::1)$/', $_SERVER['REMOTE_ADDR']) == 1);
	define('HTTP_METHOD', strtoupper($_SERVER['REQUEST_METHOD']));
}else{
  // cli 模式下特殊对待
  define('IS_LOCAL_REQUEST', true);
  define('PROJECT_URL', PROJECT_PATH);
  define('UPLOAD_URL', PROJECT_PATH.'uploads'.DS); //UPLOAD URL路径
  define('PLUGIN_URL', PROJECT_PATH.'plugins'.DS); //plugins URL路径
}


define('VENDOR_PATH', PROJECT_PATH.'vendor'.DS); //VENDOR文件路径
define('UPLOAD_PATH', PROJECT_PATH.'uploads'.DS); //UPLOAD 文件路径

define('STORAGE_PATH', PROJECT_PATH.'storage'.DS); //可写路径，不可通过url直接访问



// 配置分页信息
define('PAGE_ROW_COUNT', 20);
// MySQL配置信息
define('MySQL_DB_HOST', '127.0.0.1');
define('MySQL_DB_NAME', 'rzyx');
define('MySQL_DB_PORT', 3306);
define('MySQL_DB_USER', 'root');
define('MySQL_DB_PWD', '123456');
// MySQL配置信息
define('MSSQL_DB_HOST', '10.10.10.x');
define('MSSQL_DB_NAME', 'xxx');
define('MSSQL_DB_PORT', 1433);
define('MSSQL_DB_USER', 'xxx');
define('MSSQL_DB_PWD', 'xxx');



// 设置时区：东八区
date_default_timezone_set('PRC');

// 页面可以在相同域名页面的 frame 中展示
// header('X-Frame-Options:SAMEORIGIN');

// 所有本地请求视为调试，输出错误原因，禁止缓存
if(IS_LOCAL_REQUEST === true){
  ini_set("display_errors", "On");
  error_reporting(E_ALL & ~ E_DEPRECATED & ~ E_NOTICE);

  header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
  header('Cache-Control: no-store, no-cache, must-revalidate');
}

// 禁止访问可写路径
if(strpos(getcwd() . DS, STORAGE_PATH) !== false){
  exit('程序已终止执行，路径访问异常！！');
}


// 该函数将加载器放入队列中，按先后顺序逐个执行，直到找到类文件为止
// 故不用担心它和 Composer的加载机制相互冲突
function spl_autoload_handler_0fjdk3s2a ($class){
  // 仅自动加载LIB_PATH下的class文件
  if(file_exists(LIB_PATH . $class . '.class.php')){
    include(LIB_PATH . $class . '.class.php');
  }
}
spl_autoload_register('spl_autoload_handler_0fjdk3s2a');


// 处理异常函数
function exception_handler_0fjdk3s2a ($e){
  
  if (!headers_sent()) {
    header('Content-type: text/html; charset=utf-8');
  }
  $desc = 'Oops..., your program encounters a problem!'.CRLF;
  $desc = $desc.'#> ExceptionType: '.get_class($e).CRLF;
  $desc = $desc.'#> ErrorMessage: '.$e->getMessage().CRLF;
  $desc = $desc.'#> ErrorFile: '.str_ireplace(PROJECT_PATH, '', $e->getFile()).CRLF;
  $desc = $desc.'#> ErrorLine: '.$e->getLine().CRLF;
  $desc = $desc.'#> ErrorTrace:'.CRLF;


  $traces = $e->getTrace();
  foreach ($traces as $k => &$trace) {
    if ($trace['file'] != null) {
      try {
        if ($trace['class'] != null) {
          $reflection = new ReflectionMethod($trace['class'], $trace['function']);
          $desc .= '->' . $trace['class'].$trace['type'].$trace['function'].'(..) ';
          $desc .= "on line '{$trace['line']}' In file '{$trace['file']}'".CRLF;
        } else if($trace['function'] != null && $trace['function'] != 'include') {
          $reflection = new ReflectionFunction($trace['function']);
          $desc .= '->' . $trace['function'].'(..) ';
          $desc .= "on line '{$trace['line']}' In file '{$trace['file']}'".CRLF;
        }
      } catch (Exception $e) {
        continue;
      }
    }
  }

  $detail = str_repeat("=", 120).CRLF;
  $detail = $detail.'Unix-Timestamp: '.date('Y-m-d H:i:s').CRLF;
  $detail = $detail.'HTTP_REQUEST_URI: '.$_SERVER['REQUEST_URI'].CRLF;
  $detail = $detail.'HTTP_VAR $_POST: '.var_export($_POST, true).CRLF;
  $detail = $detail.'HTTP_VAR $_FILES: '.var_export($_FILES, true).CRLF;
  $detail = $detail.'HTTP_VAR $_SESSION: '.var_export($_SESSION, true).CRLF;
  $detail = $detail.'HTTP_VAR $_COOKIE: '.var_export($_COOKIE, true).CRLF;
  $detail = $detail.$desc;
  
  if (!file_exists(STORAGE_PATH)) {
    mkdir(STORAGE_PATH, 0644, true);
  }
    
  $err_file = STORAGE_PATH . 'error.log';
  $err_arc_file = STORAGE_PATH . 'error_arc.log';
  //限制日志文件大小256KB,每次超出后进行归档(保证总是能查看最近256KB的日志)
  if (file_exists($err_file) && filesize($err_file) >= 256000) {
    if(file_exists($err_arc_file)){
      unlink($err_arc_file);
    }
    copy($err_file, $err_arc_file);
    unlink($err_file);
  }
  file_put_contents($err_file, $detail, FILE_APPEND | LOCK_EX);
  if(IS_LOCAL_REQUEST === false){
    //输出安全的异常提示信息，并结束程序。
    exit('程序异常结束，请联系管理员！');
  }

  echo nl2br(htmlentities($desc, ENT_QUOTES, 'UTF-8'));
  echo "<a class='tip-danger pointer' href='javascript:window.history.go(-1)'>点击我返回</a>";
  exit(1); //结束程序
}

set_exception_handler('exception_handler_0fjdk3s2a');

// 处理错误函数
function error_handler_0fjdk3s2a ($errno, $msg, $file, $line){
  switch ($errno) {
    case E_ERROR:
    case E_USER_ERROR:
      $errorLevel = 'FATAL_ERROR';
      break;
    case E_WARNING:
    case E_USER_WARNING:
      $errorLevel = 'WARNING_ERROR';
      break;
    case E_NOTICE:
    case E_USER_NOTICE:
      $errorLevel = 'NOTICE_ERROR';
      break;
    default:
      $errorLevel = 'UNKNOWN_ERROR';
  }
  throw new ErrorException($errorLevel .', '. $msg, 0, $errno, $file, $line);
}
set_error_handler('error_handler_0fjdk3s2a', error_reporting());


// 如果在项目中存在vendor/autoload.php文件(含有Composer)，则加载它
$_composer_auto_loader_file_0fjdk3s2a = VENDOR_PATH . 'autoload.php';
if(file_exists($_composer_auto_loader_file_0fjdk3s2a)){
	include_once $_composer_auto_loader_file_0fjdk3s2a;
}


// 如果以'_token_'关键字开头，则进行表单token验证，
// 将验证代码封装在函数中防止污染全局变量
// 验证Token的结果并保存，方便手动查看
function form_token_auto_verify_0fjdk3s2a (){
  if($_SERVER['REQUEST_METHOD'] == 'POST' && is_array($_POST)){
    foreach($_POST as $key => &$val){
      if(is_string($val) && substr($key, 0, 4) == 'ftk_'){
        $store = new Session();
        $util = new Utility();
        if(strlen($val) > 128 || !$store->verifyToken($key, $val)){
          $util->jsAlert('令牌错误，请重新提交表单！','?');
        }
        unset($_POST[$key]);
      }
    }
  }
}

// 立即启用表单token自动验证
form_token_auto_verify_0fjdk3s2a();

// 锁定系统仅对管理员放行
function access_locked_0fjdk3s2a(){
  
}


// $fp=fsockopen('localhost',80, $errno, $errstr, 5);
// if($fp){
// 	$request_0fjdk3s2a="GET /xsgl/async.php?r=0fjdk3s2a HTTP/1.1\r\n";

// 	$request_0fjdk3s2a.="Host: localhost\r\n";
// 	$request_0fjdk3s2a.="\r\n";

// 	fputs($fp, $request_0fjdk3s2a);

// 	fclose($fp);
// }


